<!-- 员工模块 -->
<template>
  <div class="employees-container">
    <div class="app-container">
      <page-tools>
        <template #slot-left>
          当前共有{{ total }}条记录
        </template>
        <template #slot-right>
          <el-button v-power="'import'" type="danger" size="small" @click="exportBtnFn">普通excel导出</el-button>
          <el-button v-power="'import'" type="info" size="small" @click="exportBtnFn">负责excel导出</el-button>
          <el-button v-power="'import'" type="success" size="small" @click="uploadExcelBtnFn">excel导入</el-button>
          <el-button type="primary" size="small" @click="addEmpShowDialogFn">新增员工</el-button>
        </template>
      </page-tools>
      <el-card style="margin-top: 10px;">
        <el-table border :data="employeesList" :default-sort="{prop: 'workNumber'}">
          <el-table-column label="序号" type="index" />
          <el-table-column label="姓名" prop="username" />
          <el-table-column label="头像" prop="staffPhoto">
            <template v-slot="scope">
              <image-holder :src="scope.row.staffPhoto" alt="" height="80px" width="80px" style="margin: auto;" />
            </template>
          </el-table-column>
          <el-table-column label="手机号" prop="mobile" />
          <el-table-column label="工号" prop="workNumber" sortable :sort-method="workNumberSortFn" />
          <el-table-column label="聘用形式" prop="formOfEmployment" :formatter="formatter" />
          <el-table-column label="部门" prop="departmentName" />
          <el-table-column label="入职时间" prop="timeOfEntry">
            <template v-slot="scope">
              <span>{{ scope.row.timeOfEntry? scope.row.timeOfEntry.substr(0,10):"未知" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="280">
            <!-- 使用作用域插槽 -->
            <template v-slot="scope">
              <el-button type="text" size="small" @click="$router.push(`/employees/detail?id=${scope.row.id}&form=${scope.row.formOfEmployment}`)">查看</el-button>
              <el-button type="text" size="small">转正</el-button>
              <el-button type="text" size="small">调岗</el-button>
              <el-button type="text" size="small">离职</el-button>
              <el-button type="text" size="small" @click="setEmp(scope.row.id)">角色</el-button>
              <el-button type="text" size="small" @click="delEmp(scope.row.id)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页组件 -->
        <el-row type="flex" justify="center" align="middle" style="height: 60px">
          <!-- 分页区域 -->
          <el-pagination
            :current-page="query.page"
            :page-sizes="[10, 15, 20, 25]"
            :page-size="query.size"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-row>
      </el-card>
      <!-- 新增员工弹窗 -->
      <el-dialog
        title="新增员工"
        :visible.sync="showAddEmployeesDialog"
        width="50%"
        :before-close="handleClose"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
      >
        <el-form ref="formRef" label-width="120px" :model="formData" :rules="rules">
          <el-form-item label="姓名" prop="username">
            <el-input v-model="formData.username" style="width:50%" placeholder="请输入姓名" />
          </el-form-item>
          <el-form-item label="手机" prop="mobile">
            <el-input v-model="formData.mobile" style="width:50%" placeholder="请输入手机号" />
          </el-form-item>
          <el-form-item label="入职时间" prop="timeOfEntry">
            <el-date-picker v-model="formData.timeOfEntry" style="width:50%" placeholder="请选择入职时间" />
          </el-form-item>
          <el-form-item label="聘用形式" prop="formOfEmployment">
            <el-select v-model="formData.formOfEmployment" style="width:50%" placeholder="请选择" value="">
              <el-option
                v-for="item in hireType"
                :key="item.id"
                :label="item.value"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="工号" prop="workNumber">
            <el-input v-model="formData.workNumber" style="width:50%" placeholder="请输入4-6位工号" />
          </el-form-item>
          <el-form-item label="部门" prop="departmentName">
            <el-input v-model="formData.departmentName" style="width:50%" placeholder="请选择部门" @focus="departmentNameFocus" />
            <div v-if="showTree" class="tree-box">
              <el-tree :data="treeData" default-expand-all :props="{ label: 'name' }" @node-click="treeClick" />
            </div>
          </el-form-item>
          <el-form-item label="转正时间">
            <el-date-picker v-model="formData.correctionTime" style="width:50%" placeholder="请选择转正时间" />
          </el-form-item>
          <el-form-item>
            <el-button @click="addCancel">取消</el-button>
            <el-button type="primary" @click="addSubmit">确定</el-button>
          </el-form-item>
        </el-form>
      </el-dialog>
      <!-- 员工-分配角色权限 - 弹窗 -->
      <el-dialog title="分配角色" :visible.sync="showRoleDialog" @close="cancleDialog">
        <!-- 设置角色组件 -->
        <assign-role-dialog ref="assignRoleDialog" :show.sync="showRoleDialog" :all-role-list="allRoleList" @addRoleEV="addRoleFn" />
      </el-dialog>
    </div>
  </div>
</template>

<script>
import { getEmployeeListAPI, saveAssignRolesAPI, departmentsListAPI, addEmployeeAPI, delEmployeeAPI, getUserDetailByIdAPI, getRolesAPI } from '@/api'
import AssignRoleDialog from './components/assignRoleDialog.vue'
import PageTools from '@/components/PageTools'
import Employees from '@/api/constant'
import { transTree } from '@/utils'
import ImageHolder from '@/components/ImageHolder'

export default {
  name: 'Employees',
  components: {
    PageTools,
    ImageHolder,
    AssignRoleDialog
  },
  data () {
    return {
      query: {
        page: 1, // 页码
        size: 10 // 每页条数
      },
      employeesList: [], // 保存某页员工列表
      allEmployeesList: [], // 保存所有员工列表
      total: 0, // 数据总条数
      showAddEmployeesDialog: false, // 控制新增员工的遮罩层
      // 新增员工数据
      formData: {
        username: '', // 用户名
        mobile: '', // 手机号
        formOfEmployment: '', // 聘用形式
        workNumber: '', // 工号
        departmentName: '', // 部门
        timeOfEntry: '', // 入职时间
        correctionTime: '' // 转正时间
      },
      hireType: Employees.hireType, // 聘用形式数据绑定
      // 表单验证规则
      rules: {
        username: [
          { required: true, message: '用户姓名不能为空', trigger: 'blur' },
          { min: 1, max: 4, message: '用户姓名为1-4位', trigger: 'blur' }
        ],
        mobile: [
          { required: true, message: '手机号不能为空', trigger: 'blur' },
          { pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' }
        ],
        formOfEmployment: [
          { required: true, message: '聘用形式不能为空', trigger: 'blur' }
        ],
        workNumber: [
          { required: true, message: '工号不能为空', trigger: 'blur' },
          { pattern: /^[a-zA-Z0-9]{4,6}$/, message: '工号格式不正确', trigger: 'blur' }
        ],
        departmentName: [
          { required: true, message: '部门不能为空', trigger: 'change' }
        ],
        timeOfEntry: [
          { required: true, message: '请选择入职时间', trigger: 'blur' }
        ]
      },
      treeData: [], // 保存树状部门列表
      showTree: false, // 是否显示树形组件
      clickDepartName: '', // 点击的部门名字
      showRoleDialog: false, // 分配角色的弹窗显示与隐藏
      allRoleList: [], // 保存所有角色对象
      clickEmpId: '' // 中转员工ID值
    }
  },
  watch: {
    'formData.departmentName'(newVal) {
      if (newVal !== this.clickDepartName) {
        this.formData.departmentName = this.clickDepartName
      }
    }
  },
  created() {
    // 组件创建成功后，请求页面数据
    this.getEmployeeList()
    this.getDepartments()
    this.getRolesFn()
  },
  methods: {
    // 权限更新保存的事件
    async addRoleFn(roleIds) {
      // 发送请求
      const res = await saveAssignRolesAPI({
        id: this.clickEmpId,
        roleIds
      })
      if (!res.success) return this.$message.error(res.message)
      this.$message.success(res.message)
    },
    // 关闭分配角色弹框
    cancleDialog() {
      this.showRoleDialog = false
    },
    // 点击分配角色的事件
    async setEmp(empId) {
      // 后台发送
      const res = await getUserDetailByIdAPI(empId)
      // 弹窗
      this.showRoleDialog = true
      // 保存中转ID值
      this.clickEmpId = empId
      this.$nextTick(() => {
        // 将权限点id值传递给弹窗组件
        this.$refs.assignRoleDialog.roleIdList = res.data.roleIds
      })
    },
    // 向后台请求，获取角色列表
    async getRolesFn() {
      // 第一次请求，获取角色总数
      const res = await getRolesAPI({
        page: 1,
        pageSize: 10
      })
      // 第二次请求，获取所有数据
      const allRes = await getRolesAPI({
        page: 1,
        pagesize: res.data.total
      })
      this.allRoleList = allRes.data.rows
    },
    // excel导出
    exportBtnFn() {
      import('@/vendor/Export2Excel').then(excel => {
        const tHeader = ['序号', '姓名', '头像', '手机号', '工号', '聘用形式', '部门', '入职时间']

        // const newArr = this.employeesList.map(obj => {
        //   return Object.values(obj)
        // })
        // 报错，取出的值是无序的，没办法跟表格数据对上
        // 解决：使用映射，
        // 1.中文——>英文的映射关系(枚举值)
        const zhAndEnObj = {
          '姓名': 'username',
          '头像': 'staffPhoto',
          '手机号': 'mobile',
          '工号': 'workNumber',
          '聘用形式': 'formOfEmployment',
          '部门': 'departmentName',
          '入职时间': 'timeOfEntry'
        }
        // 2.遍历每一个英文对象
        const data = this.allEmployeesList.map((enObj, index) => {
          // 新数组，用于保存格式化好的数据
          const newArr = []
          // 3.遍历表格头部
          tHeader.forEach(zhKey => {
            if (zhKey === '序号') {
              newArr.push(index + 1)
            } else {
              // 换出来英文的表头值
              const enKey = zhAndEnObj[zhKey]
              // 取出来对应的key值
              let value = enObj[enKey]
              // 格式化聘用形式
              if (zhKey === '聘用形式') {
                if (value === 1 || value === '1') {
                  value = '正式'
                } else if (value === 2 || value === '2') {
                  value = '非正式'
                } else {
                  value = '其他'
                }
              }
              // 将数据添加到新数组中
              newArr.push(value)
            }
          })
          // 4.将新数组返回出去
          return newArr
        })
        // export_json_to_excel()就是vendor/Export2Excel.js文件内封装的导出excel文件的方法
        excel.export_json_to_excel({
          // 表格文件的列标题
          header: tHeader,
          // 表格正文数据，是一个二维数组，行列
          data,
          // 导出时的文件名(无需后缀)
          filename: '员工信息',
          // 单元格宽度是否自适应
          autoWidth: true,
          // 保存文件的后缀
          bookType: 'xlsx'
        })
        this.downloadLoading = false
      })
    },
    // excel导入操作
    uploadExcelBtnFn() {
      console.log(this.formData)
      this.$router.push('/excel')
    },
    // 树状图点击事件
    treeClick(data) {
      if (!data.children) {
        this.formData.departmentName = data.name
        this.showTree = false
        // 临时保存点击的部门名字
        this.clickDepartName = data.name
      }
    },
    // 部门选择聚焦事件
    departmentNameFocus() {
      this.showTree = true
    },
    // 获取部门数据
    async getDepartments() {
      const res = await departmentsListAPI()
      if (!res.success) return this.$message.error(res.message)
      this.treeData = transTree(res.data.depts, '')
    },
    // 员工列-自定义排序
    workNumberSortFn(a, b) {
    // 打印a和b发现是表格数组里的对象
    // sort方法使用:
    // 如果return小于0, 那么 a 会被排列到 b 之前
    // 如果return等于0, 那么 a 和 b 位置不变
    // 如果return大于0, 那么 a 会被排列到 b 之后
      return parseInt(a.workNumber) - parseInt(b.workNumber)
    },
    // 格式化表格的某一项
    formatter(row, column, cellValue, index) {
      // 用数组的 find 方法找到 id = 1 的元素，再取出它的 value
      const obj = Employees.hireType.find((item) => item.id === cellValue)
      return obj ? obj.value : '未知'
    },
    // 每页显示的条数发生改变时触发
    handleSizeChange(newSize) {
      this.query.size = newSize
      this.getEmployeeList()
    },
    // 当前页面发生改变时触发
    handleCurrentChange(newPage) {
      this.query.page = newPage
      this.getEmployeeList()
    },
    // 请求，获取后台员工列表
    async getEmployeeList() {
      // 第一次请求：请求某页的数据，获取总数量
      // 后台请求
      const res = await getEmployeeListAPI(this.query)
      // 根据返回的状态码给用户提示
      if (!res.success) return this.$message.error(res.message)
      // 请求成功
      // 保存员工数据
      this.employeesList = res.data.rows
      // 保存总页数
      this.total = res.data.total

      // 第二次请求：保存所有数据
      const allRes = await getEmployeeListAPI({
        page: 1, // 页码
        size: res.data.total // 总数
      })
      this.allEmployeesList = allRes.data.rows
    },
    // 新增员工
    addEmpShowDialogFn() {
      this.showAddEmployeesDialog = true
    },
    // 控制新增员工的遮罩层关闭之前回调函数
    handleClose() {
      this.showAddEmployeesDialog = false
    },
    // 新增员工取消按钮
    addCancel() {
      // 关闭弹窗
      this.showAddEmployeesDialog = false
      // 清空表单
      this.formData = {}
      this.clickDepartName = ''
      // 对表单进行重置
      this.$refs.formRef.resetFields()
    },
    // 新增员工确认按钮
    addSubmit() {
      // 兜底校验
      this.$refs.formRef.validate(async valide => {
        if (valide) {
          // 添加请求
          const res = await addEmployeeAPI(this.formData)
          // 请求失败谈报错
          if (!res.success) return this.$message.error(res.message)
          // 请求成功 重新获取列表
          // 重新获取列表
          this.getEmployeeList()
          // 关闭弹窗
          this.showAddEmployeesDialog = false
        }
      })
    },
    // 删除员工
    async delEmp(id) {
      const delRes = await this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(err => {
        return err
      })
      // 删除取消按钮
      if (delRes === 'cancel') return this.$message.info('您取消了删除')
      // 删除请求
      const res = await delEmployeeAPI(id)
      // 删除失败
      if (!res.success) return this.$message.error(res.message)
      // 删除成功后的提示
      this.$message.success(res.message)
      console.log(this.employeesList)
      // 解决删除最后一页只有一个数据的页面不切换问题
      if (this.employeesList.length === 1) {
        this.query.page--
      }
      // 重新渲染页面
      this.getEmployeeList()
    }
  }
}
</script>

<style lang="scss" scoped>

</style>
